from celery import shared_task
import logging
from functools import wraps

logger = logging.getLogger('tasks')

"""
自定义任务装饰器 - 自动处理系统追踪参数

系统会自动向所有任务注入以下追踪参数:
- tasks_instance_id: 任务实例ID,用于关联任务执行结果
- periodic_task_name: 周期任务名称,用于查询历史执行记录

使用方法:
@celery_task
def my_task(arg1, arg2):
    # 不需要声明 **kwargs,系统参数会自动过滤
    pass
"""

def celery_task(func):
    """
    自定义Celery任务装饰器
    自动过滤系统注入的追踪参数,使任务函数只接收业务参数
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 系统追踪参数列表
        system_params = ['tasks_instance_id', 'periodic_task_name']
        
        # 分离业务参数和系统参数
        business_kwargs = {k: v for k, v in kwargs.items() if k not in system_params}
        system_kwargs = {k: v for k, v in kwargs.items() if k in system_params}
        
        # 记录系统追踪信息(调试用)
        if system_kwargs:
            logger.debug(f"任务 {func.__name__} 接收到业务输入参数: {business_kwargs}")
            logger.debug(f"任务 {func.__name__} 追踪信息: {system_kwargs}")
        
        # 调用原始函数,只传递业务参数
        return func(*args, **business_kwargs)
    
    # 应用 @shared_task 装饰器到 wrapper，并明确指定任务名称
    # 使用 name 参数确保任务名称与原函数名一致
    return shared_task(name=func.__name__)(wrapper)

@celery_task
def example_task(*args, **kwargs):
    """示例任务,可以根据需要添加更多任务
    
    使用自定义装饰器后,系统参数会自动过滤,这里收到的 kwargs 只包含业务参数
    """
    logger.info(f"任务执行成功,参数: args={args}, kwargs={kwargs}")
    return f"任务执行成功,参数: args={args}, kwargs={kwargs}"

@celery_task
def send_email_task(recipient, subject, **kwargs):
    """发送邮件任务
    
    参数:
        recipient: 收件人
        subject: 邮件主题
        **kwargs: 其他业务参数(系统参数已自动过滤)
    """
    logger.info(f"发送邮件任务执行: recipient={recipient}, subject={subject}, 其他参数={kwargs}")
    return f"邮件已发送给 {recipient},主题: {subject}"

@celery_task
def data_backup_task(backup_path, task_id=None, **kwargs):
    """数据备份任务
    
    参数:
        backup_path: 备份路径
        task_id: 任务ID(可选)
        **kwargs: 其他业务参数(系统参数已自动过滤)
    """
    logger.info(f"数据备份任务执行: backup_path={backup_path}, task_id={task_id}, 其他参数={kwargs}")
    return f"数据已备份到 {backup_path}"

@celery_task
def ldap_sync_users_task(import_ou=None, sync_disabled=True, sync_existing=True):
    """LDAP用户同步任务
    
    参数:
        import_ou: 导入用户的OU (如果为空，使用basedn)
        sync_disabled: 是否同步用户过期时间到本地
        sync_existing: 是否更新用户手机号
    """
    from system.models import SysConfig
    from utils.CommonUtils import LdapEntity, get_object
    
    try:
        # 获取LDAP配置
        ldap_config = get_object(SysConfig, name='ldap')
        if not ldap_config or not ldap_config.json_value.get('enabled'):
            error_msg = 'LDAP未启用或配置不存在'
            logger.error(error_msg)
            return {'success': False, 'message': error_msg}
        
        # 创建LDAP实体并同步用户
        ldap = LdapEntity(ldap_config.json_value)
        success_count, fail_count, details = ldap.sync_users(
            import_ou=import_ou,
            sync_disabled=sync_disabled,
            sync_existing=sync_existing
        )
        
        result_msg = f'同步完成: 成功 {success_count} 个, 失败 {fail_count} 个'
        logger.info(result_msg)
        
        return {
            'success': True,
            'message': result_msg,
            'success_count': success_count,
            'fail_count': fail_count,
            'details': details[:100]  # 只返回前100条详细信息
        }
    except Exception as e:
        error_msg = f'LDAP同步任务执行失败: {str(e)}'
        logger.error(error_msg)
        return {'success': False, 'message': error_msg}
